﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static HartConfigTool.CommandDebugForm;

namespace HartConfigTool
{
    // Table
    // Table 16.Loop Current Mode Codes
    public enum EnumLoopCurrentModeCodes : byte
    { 
        eDisabled = 0,
        eEnabled = 1,
        eNotUsed = 250,
        eNone = 251,
        eUnknown = 252,
        eSpecial = 253,
    }
    
    public class HARTProtocolV7
    {
        // Table
        // Table 2.Engineering Unit Codes
        public static Dictionary<int, string> EngineeringUnitCodes = new Dictionary<int, string>()
        {
            // Pressure
            {1, "inches of water at 68 degrees F" },
            {2, "inches of mercury at 0 degrees C"},
            {3, "feet of water at 68 degrees F" },
            {4, "millimeters of water at 68 degrees F" },
            {5, "millimeters of mercury at 0 degrees C" },
            {6, "pounds per square inch" },
            {7, "bars" },
            {8, "millibars" },
            {9, "grams per square centimeter" },
            {10, "kilograms per square centimeter" },
            {11, "pascals" },
            {12, "kilopascals" },
            {13, "torr" },
            {14, "atmospheres" },
            {145, "inches of water ata 60 degrees F" },
            {237, "megapascals" },
            {238, "inches of water at 4 degree C" },
            {239, "millimeters of water at 4 degrees C" },
        };
        // Table 16.Loop Current Mode Codes
        public static Dictionary<byte, string> LoopCurrentModeCodes = new Dictionary<byte, string>()
        {
            { 0, "Disabled"},
            { 1, "Enabled"},
            { 250, "Not Used"},
            { 251, "None"},
            { 252, "Unknown"},
            { 253, "Special"},
        };

        public HartMsgProResult hartMsg;
        public enum HartStatusCode
        { 
            eCRC_ERROR = 0x00, 
            eCRC_SUCCESS = 0x01,

            ePREAMBLES_EXCEED = 0x02,

            eDATA_FRAME_ERROR = 0x10,
            eDATA_FRAME_CRC_ERROR = 0x11,
            eDATA_FRAME_WAITING = 0x12,
            eDATA_FRAME_REV_FINISH = 0x13,
        };
        //private Hashtable h_Universal = new Hashtable();
        public static string[] UniversalCmd =
        {
            "#0 ReadUniqueIdentifier",
            "#1 ReadPrimaryVariable",
            "#2 ReadPVCurrentAndPerOfRange",
            "#3 ReadDynamicVariablesAndLoopCurrent",
            "#6 WritePollingAddress",
            "#12 ReadMessage",
            "#14 ReadPVTansducerInfo",
            "#15 ReadDeviceInformation",
        };
        public static string[] Cmd0ParameterList =
        {
            "Byte0 \'254\'",
            "Byte1-2 Expanded Device Type",
            "Byte3 Min Preambles(M2S)",
            "Byte4 HART Revision",
            "Byte5 Device Revision Level",
            "Byte6 Software Revision",
            "Byte7 Hardware Revision",
            "Byte7 Physical Signaling",
            "Byte8 Flags",
            "Byte9-11 Device ID",
            "Byte12 Min Preambles(S2M)",
            "Byte13 Max Device Variables",
            "Byte14-15 Config Change Counter",
            "Byte16 Extended Field Dev Status",
            "Byte17-18 Manufacturer Id Code",
            "Byte19-20 Private Lab Distri Code",
            "Byte21 Device Profile"
        };

        public struct HartMsgProResult
        {
            public HartStatusCode status { get; set; }
            public byte[] data { get; set; }
        };
        public static bool VerifyDataIsComplete(byte[] bytes)
        {
            byte ucCRC = 0;
            byte frameSize = 0;
            byte frameStartPos = 0;

            if ((bytes == null) || (bytes.Length == 0))
            {
                return false;
            }

            if (bytes.Length >= 8)
            {
                if ((bytes[4] == 0x06) || (bytes[4] == 0x86))
                {
                    frameStartPos = 4;
                }
                else if ((bytes[5] == 0x06) || (bytes[5] == 0x86))
                {
                    frameStartPos = 5;
                }
                else if ((bytes[6] == 0x06) || (bytes[6] == 0x86))
                {
                    frameStartPos = 6;
                }
                else if ((bytes[7] == 0x06) || (bytes[7] == 0x86))
                {
                    frameStartPos = 7;
                }
                else
                { 
                    return false;
                }

                switch (bytes[frameStartPos])
                {
                    case 0x06:
                        frameSize = (byte)(4 + bytes[frameStartPos + 3] + 1);
                        break;
                    case 0x86:
                        frameSize = (byte)(8 + bytes[frameStartPos + 7] + 1);
                        break;
                    default:
                        break;
                }

                if ((bytes.Length - frameStartPos) >= frameSize)
                {
                    byte[] frameData = new byte[frameSize];

                    Array.Copy(bytes, frameStartPos, frameData, 0, frameSize);

                    ucCRC = HARTProtocolV7.GetCRC(frameData, (byte)(frameSize - 1));

                    if (ucCRC == frameData[frameSize - 1])
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        public static byte GetCRC(byte[] pData, byte size)
        {
            byte ucCRC = 0;
            byte i = 0;

            for (i = 0; i < size; i++)
            {
                ucCRC ^= pData[i];
            }

            return ucCRC;
        }
        static public string HexToString(byte[] data)
        {
            string resultStr = null;

            for (byte i = 0; i < data.Length; i++)
            {
                if (i == (data.Length - 1))
                {
                    resultStr += data[i].ToString("X2");
                }
                else
                {
                    resultStr += data[i].ToString("X2") + ", ";
                }
            }

            return resultStr;
        }
        public static byte[] GetDataFrame(byte[] data)
        {
            byte frameStart = 0;

            for (byte i = 0; i < data.Length; i++)
            {
                if ((data[i] == 0x06) || (data[i] == 0x86))
                {
                    frameStart = i;
                    break;
                }
            }

            if (frameStart != 0)
            {
                ArraySegment<byte> segment = new ArraySegment<byte>(data, frameStart, data.Length - frameStart);
                return segment.ToArray();
            }

            return null;
        }
    }
}
